package com.tulei.framework.interceptor;

import cn.dev33.satoken.stp.StpInterface;
import com.tulei.common.constant.RedisConstant;
import com.tulei.common.utils.RedisUtils;
import com.tulei.system.Entity.SysRole;
import com.tulei.system.mapper.PermMapper;
import com.tulei.system.mapper.RoleMapper;

import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 自定义权限验证接口扩展
 */
@Component
@RequiredArgsConstructor
public class StpInterfaceImpl implements StpInterface {


    private final RoleMapper roleMapper;

    private final PermMapper permMapper;

    private final RedisUtils redisUtils;

    /**
     * 返回一个账号所拥有的权限码集合
     */
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {

        final String permsKey = RedisConstant.perms + loginId;

        // 直接尝试从Redis获取perms，使用Optional处理可能的null值
        List<String> perms = Optional.ofNullable((List<String>) redisUtils.get(permsKey))
                .orElseGet(() -> {
                    // 从数据库获取perms
                    List<String> Perms = permMapper.getPermsById(Long.parseLong(loginId.toString()));

                    // 如果数据库中有数据，则缓存并返回
                    if (!CollectionUtils.isEmpty(Perms)) {
                        redisUtils.set(permsKey, Perms);
                    }
                    return Perms;
                });

        return perms;
    }

    /**
     * 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
     */
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {

        final String rolesKey = RedisConstant.roles + loginId;
        List<String> roles = (List<String>) redisUtils.get(rolesKey);

        if (CollectionUtils.isEmpty(roles)) {
            // 从数据库获取当前用户角色
            SysRole userRole = roleMapper.getRoleById(Long.parseLong(loginId.toString()));
            if (userRole == null) {
                return Collections.emptyList();
            }
            // 从Redis获取全部角色列表，若无则查询数据库并缓存
            List<SysRole> allRoles = (List<SysRole>) redisUtils.get(RedisConstant.getList_Role);
            if (CollectionUtils.isEmpty(allRoles)) {
                allRoles = roleMapper.selectList(null);
                redisUtils.set(RedisConstant.getList_Role, allRoles);
            }
            // 过滤出权限大于等于当前用户角色的所有角色的名称
            roles = allRoles.stream()
                    .filter(role -> role.getAccess() >= userRole.getAccess())
                    .map(SysRole::getRoleName)
                    .collect(Collectors.toList());

            // 将结果缓存到Redis
            redisUtils.set(rolesKey, roles);
        }
        return roles;
    }
}